package czk.concrent.syn.objectheader;

import java.util.concurrent.TimeUnit;

/**
 *
 * 在Java中，当一个对象被synchronized关键字锁定，并且升级为重量级锁（即发生了锁膨胀）之后，该对象的对象头中的部分信息会发生变化。具体来说，对象头的一部分空间会被用来存储指向锁记录（Lock Record）的指针，而不再直接存储hash code。
 *
 * 在这种情况下，如果你尝试获取这个对象的hashCode，JVM会如何处理呢？以下是详细的解释：
 *
 * 获取hashCode的过程
 * 轻量级锁或无锁状态：当对象处于轻量级锁或者完全未加锁的状态时，其对象头中的Mark Word部分可以存储对象的hash code（如果已经计算过）。此时调用hashCode方法可以直接从对象头读取已有的hash code值。
 * 重量级锁状态：一旦对象升级为重量级锁，对象头的Mark Word部分将不再保存hash code，而是用于其他用途，如存储指向锁记录的指针。因此，在这种状态下，当你请求对象的hashCode时，JVM会检查对象头以确定hash code是否已经存在。
 * 如果hash code已经被计算并且存储在对象头中，则直接返回该值。
 * 如果hash code尚未计算或者因为锁膨胀而不在对象头中，JVM将会：
 * 计算对象的hash code（基于对象的内容或其他机制）。
 * 将新计算出的hash code存储在一个称为“偏移量”的位置——通常是在对象实例数据区的某个固定偏移量处，而不是在对象头里。
 * 返回计算后的hash code给调用者。
 * 后续访问：一旦hash code被计算并存储在对象实例数据区后，未来的hashCode调用将直接从这个位置读取，即使对象仍然处于重量级锁状态。
 * 总结
 * 所以，当一个对象由于synchronized锁膨胀成为重量级锁时，它的hash code不会丢失，只是存放的位置变了。初次调用hashCode可能会触发一次计算并将结果存放在对象的数据区域，之后的所有调用都可以快速地从那里读取到hash code。这种方式确保了即使在锁膨胀的情况下，对象的hash code功能也能正常工作，不影响程序的行为。
 *
 * @author chenzhangkun
 * @ClassName ObjectHeaderDemo1
 * @description: TODO
 * @date 2024年12月26日
 */
public class ObjectHeaderDemo1 {

	public static Object object=new Object();
	public static void main(String[] args) throws Exception{
		System.out.println(object.hashCode());
		new Thread(()-> {
			try {
				method();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}).start();


		new Thread(()-> {
			try {
				method();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}).start();


		TimeUnit.SECONDS.sleep(3);

		System.out.println(object.hashCode());

	}
	public static void method() throws InterruptedException {
		synchronized (object){
			TimeUnit.SECONDS.sleep(10);
			System.out.println("获取到锁");
		}


	}

}
